package org.beetl.sql2o.data;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.beetl.sql2o.Sql2oException;
import org.beetl.sql2o.converters.BigDecimalConverter;
import org.beetl.sql2o.converters.ByteConverter;
import org.beetl.sql2o.converters.Convert;
import org.beetl.sql2o.converters.ConverterException;
import org.beetl.sql2o.converters.DateConverter;
import org.beetl.sql2o.converters.DoubleConverter;
import org.beetl.sql2o.converters.FloatConverter;
import org.beetl.sql2o.converters.IntegerConverter;
import org.beetl.sql2o.converters.LongConverter;
import org.beetl.sql2o.converters.ShortConverter;
import org.beetl.sql2o.converters.StringConverter;

/**
 * Represents a result set row.
 */
public class Row {

 private final Map<Integer, Object> values;

 private final Table table;

 public Row(Table table) {
  this.table = table;
  values = new HashMap<Integer, Object>();
 }

 void addValue(int columnIndex, Object value) {
  values.put(columnIndex, value);
 }

 public Object getObject(int columnIndex) {
  return values.get(columnIndex);
 }

 public Object getObject(String columnName) {
  String col = table.isCaseSensitive() ? columnName : columnName.toLowerCase();

  Object obj;
  try {
   obj = getObject(table.getColumnNameToIdxMap().get(col));
  } catch (NullPointerException ex) {
   throw new Sql2oException(String.format("Column with name '%s' does not exist", columnName), ex);
  }

  return obj;
 }

 public <V> V getObject(int columnIndex, Class clazz) {
  try {
   return (V) Convert.getConverter(clazz).convert(getObject(columnIndex));
  } catch (ConverterException ex) {
   throw new Sql2oException("Error converting value", ex);
  }
 }

 public <V> V getObject(String columnName, Class clazz) {
  try {
   return (V) Convert.getConverter(clazz).convert(getObject(columnName));
  } catch (ConverterException ex) {
   throw new Sql2oException("Error converting value", ex);
  }
 }

 public BigDecimal getBigDecimal(int columnIndex) {
  return new BigDecimalConverter().convert(getObject(columnIndex));
 }

 public BigDecimal getBigDecimal(String columnName) {
  return new BigDecimalConverter().convert(getObject(columnName));
 }

 public Double getDouble(int columnIndex) {
  return new DoubleConverter(false).convert(getObject(columnIndex));
 }

 public Double getDouble(String columnName) {
  return new DoubleConverter(false).convert(getObject(columnName));
 }

 public Float getFloat(int columnIndex) {
  return new FloatConverter(false).convert(getObject(columnIndex));
 }

 public Float getFloat(String columnName) {
  return new FloatConverter(false).convert(getObject(columnName));
 }

 public Long getLong(int columnIndex) {
  return new LongConverter(false).convert(getObject(columnIndex));
 }

 public Long getLong(String columnName) {
  return new LongConverter(false).convert(getObject(columnName));
 }

 public Integer getInteger(int columnIndex) {
  return new IntegerConverter(false).convert(getObject(columnIndex));
 }

 public Integer getInteger(String columnName) {
  return new IntegerConverter(false).convert(getObject(columnName));
 }

 public Short getShort(int columnIndex) {
  return new ShortConverter(false).convert(getObject(columnIndex));
 }

 public Short getShort(String columnName) {
  return new ShortConverter(false).convert(getObject(columnName));
 }

 public Byte getByte(int columnIndex) {
  return new ByteConverter(false).convert(getObject(columnIndex));
 }

 public Byte getByte(String columnName) {
  return new ByteConverter(false).convert(getObject(columnName));
 }

 public Date getDate(int columnIndex) {
  try {
   return new DateConverter().convert(getObject(columnIndex));
  } catch (ConverterException e) {
   throw new Sql2oException("Could not convert column with index " + columnIndex + " to " + Date.class.toString());
  }
 }

 public Date getDate(String columnName) {
  try {
   return new DateConverter().convert(getObject(columnName));
  } catch (ConverterException e) {
   throw new Sql2oException("Could not convert column with name " + columnName + " to " + Date.class.toString());
  }
 }

 public String getString(int columnIndex) {
  try {
   return new StringConverter().convert(getObject(columnIndex));
  } catch (ConverterException e) {
   throw new Sql2oException("Could not convert column with index " + columnIndex + " to " + String.class.getName());
  }
 }

 public String getString(String columnName) {
  try {
   return new StringConverter().convert(getObject(columnName));
  } catch (ConverterException e) {
   throw new Sql2oException("Could not convert column with name " + columnName + " to " + String.class.getName());
  }
 }

}
